

#include "port/GFX_ST7789.h"

namespace GFX {

// SCREEN INITIALIZATION ***************************************************

// Rather than a bazillion writecommand() and writedata() calls, screen
// initialization commands and arguments are organized in these tables
// stored in PROGMEM.  The table may look bulky, but that's mostly the
// formatting -- storage-wise this is hundreds of bytes more compact
// than the equivalent code.  Companion function follows.

// clang-format off

static const uint8_t PROGMEM
  generic_st7789[] =  {                // Init commands for 7789 screens 
    ST77XX_SWRESET,
    ST_CMD_DELAY, //  1: Software reset, no args, w/delay
    150,          //     ~150 ms delay
    ST77XX_SLPOUT,
    ST_CMD_DELAY, //  2: Out of sleep mode, no args, w/delay
    10,           //      10 ms delay
    ST77XX_COLMOD,
    1 + ST_CMD_DELAY, //  3: Set color mode, 1 arg + delay:
    0x55,             //     16-bit color
    10,               //     10 ms delay
    ST77XX_MADCTL,
    1,    //  4: Mem access ctrl (directions), 1 arg:
    0x08, //     Row/col addr, bottom-top refresh
    ST77XX_CASET,
    4,    //  5: Column addr set, 4 args, no delay:
    0x00, //
    0,    //     XSTART = 0
    0,    //
    240,  //     XEND = 240
    ST77XX_RASET,
    4,          //  6: Row addr set, 4 args, no delay:
    0x00,       //
    0,          //     YSTART = 0
    320 >> 8,   //
    320 & 0xFF, //     YEND = 320
    ST77XX_INVON,
    ST_CMD_DELAY, //  7: hack
    10,
    ST77XX_NORON,
    ST_CMD_DELAY, //  8: Normal display on, no args, w/delay
    10,           //     10 ms delay
    ST77XX_DISPON,
    ST_CMD_DELAY, //  9: Main screen turn on, no args, delay
    10,
     0x00, 0x00, 0x00 };

static const uint8_t PROGMEM InitCfg[] = {
    BEGIN_WRITE, //
    WRITE_COMMAND_8, ST77XX_SWRESET, //
    DELAY, 50, //
    WRITE_COMMAND_8, ST77XX_SLPOUT, //
    DELAY, 10, //
    WRITE_C8_D8, ST77XX_COLMOD, 0x55, //
    DELAY, 10, //
    WRITE_C8_D8, ST77XX_MADCTL, 0x08, //

    WRITE_C8_D32, ST77XX_CASET, 0x00, 0, 0, 240, //
    WRITE_C8_D32, ST77XX_RASET, 0x00, 0, 320 >> 8, 320 &0xFF, //
    WRITE_COMMAND_8, ST77XX_INVON, //
    DELAY, 10, //
    WRITE_COMMAND_8, ST77XX_NORON, //
    DELAY, 10, //
    WRITE_COMMAND_8, ST77XX_DISPON, //
    DELAY, 10, //

    END_WRITE, //
};

// clang-format on

GFX_ST7789::GFX_ST7789(GFX_PortBase &lcd, uint16_t w, uint16_t h) : GFX_ST77xx(lcd, w, h) {
    _override_datamode = 3; //  SPI MODE 3
}

GFX_ST7789::~GFX_ST7789() {}

void GFX_ST7789::tftInit() {
    uint16_t width  = WIDTH;
    uint16_t height = HEIGHT;
    if (width == 240 && height == 240) {
        // 1.3", 1.54" displays (right justified)
        _rowstart  = (320 - height);
        _rowstart2 = 0;
        _colstart = _colstart2 = (240 - width);
    } else if (width == 135 && height == 240) {
        // 1.14" display (centered, with odd size)
        _rowstart = _rowstart2 = (int)((320 - height) / 2);
        // This is the only device currently supported device that has different
        // values for _colstart & _colstart2. You must ensure that the extra
        // pixel lands in _colstart and not in _colstart2
        _colstart  = (int)((240 - width + 1) / 2);
        _colstart2 = (int)((240 - width) / 2);
    } else {
        // 1.47", 1.69, 1.9", 2.0" displays (centered)
        _rowstart = _rowstart2 = (int)((320 - height) / 2);
        _colstart = _colstart2 = (int)((240 - width) / 2);
    }

    displayInit(generic_st7789);
    setRotation(0);
}

/**************************************************************************/
/*!
    @brief  Set origin of (0,0) and orientation of TFT display
    @param  m  The index for rotation, from 0-3 inclusive
*/
/**************************************************************************/
void GFX_ST7789::setRotation(uint8_t m) {
    uint8_t madctl = 0;
    GFX_disRGB::setRotation(m);
    switch (_rotation) {
        case 0:
            madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MY | ST77XX_MADCTL_RGB;
            break;
        case 1:
            madctl = ST77XX_MADCTL_MY | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB;
            break;
        case 2:
            madctl = ST77XX_MADCTL_RGB;
            break;
        case 3:
            madctl = ST77XX_MADCTL_MX | ST77XX_MADCTL_MV | ST77XX_MADCTL_RGB;
            break;
    }
    sendC8D8(ST77XX_MADCTL, madctl);
}

} // namespace GFX
